package npda;

import pda.PDAConfiguration;

import java.util.HashSet;
import java.util.Set;

/**
 * @author haoly
 * @title NPDA
 * @date 2025/4/22 09:39
 * @description TODO
 */
public class NPDA<T> {
    private Set<PDAConfiguration<T>> currentConfigurations;

    private final Set<T> acceptStates;

    private final NPDARulebook<T> rulebook;

    public NPDA(Set<PDAConfiguration<T>> currentConfigurations, Set<T> acceptStates, NPDARulebook<T> rulebook) {
        this.currentConfigurations = new HashSet<>(currentConfigurations);
        this.acceptStates = new HashSet<>(acceptStates);
        this.rulebook = rulebook;
    }

    public void readString(String s){
        for (int i = 0; i < s.length(); i++) {
            readChar(s.charAt(i));
        }
    }

    private void readChar(Character character) {
        Set<PDAConfiguration<T>> nextConfigs = rulebook.nextConfigurations(getCurrentConfigurations(), character);
        this.currentConfigurations = nextConfigs;
    }

    public Boolean accepting(){
        Set<T> currentState = new HashSet<>();
        Set<PDAConfiguration<T>> configurations = getCurrentConfigurations();
        for (PDAConfiguration<T> config : configurations) {
            currentState.add(config.getState());
        }
        currentState.retainAll(acceptStates);
        return currentState.size() > 0;
    }

    public Set<PDAConfiguration<T>> getCurrentConfigurations() {
        return this.rulebook.followFreeMoves(this.currentConfigurations);
    }

    public Set<T> getAcceptStates() {
        return acceptStates;
    }

    public NPDARulebook<T> getRulebook() {
        return rulebook;
    }
}
